import numpy as np
from sklearn.preprocessing import StandardScaler


def pca(X, threshold):
    # 对 X 进行标准化处理
    standard_scaler = StandardScaler()
    X_normalized = standard_scaler.fit_transform(X)
    # 计算协方差矩阵
    cov_matrix = np.cov(X_normalized, rowvar=False)
    # 计算协方差矩阵的特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
    # 特征值从大到小排序
    sorted_indices = np.argsort(eigenvalues)[::-1]
    # 计算累计方差贡献率
    variance_ratio = np.cumsum(eigenvalues[sorted_indices] / np.sum(eigenvalues))
    # 确定降维后的维度
    k = np.argmax(variance_ratio >= threshold) + 1
    # 取前 k 个特征向量构成投影矩阵 P
    top_k_indices = sorted_indices[:k]
    P = eigenvectors[:, top_k_indices]
    # 计算降维后的数据
    reduced_data = np.dot(X_normalized, P)
    return reduced_data


if __name__ == '__main__':
    m, n, threshold = 5, 5, 0.8
    X = np.random.rand(m, n)
    print("降维前: \n", X)
    reduced_data = pca(X, threshold)
    print("降维后: \n", reduced_data)
